package edu.se.jai.websocketgateway.config;

import edu.se.jai.openfeignapi.dto.GameRoomDto;
import edu.se.jai.openfeignapi.dto.Result;
import edu.se.jai.openfeignapi.feign.GameServiceFeignApi;
import edu.se.jai.websocketgateway.service.MessageSendService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.messaging.SessionDisconnectEvent;

/**
 * WebSocket事件监听器
 * 
 * 负责处理WebSocket连接事件，包括：
 * - 连接断开时的数据清理
 * - 房间创建者断线时自动解散房间
 * - 普通玩家断线时自动离开房间
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class WebSocketEventListener {

    private final GameServiceFeignApi gameServiceClient;
    private final MessageSendService messageSendService;

    /**
     * 处理WebSocket连接断开事件
     * 
     * @param event 连接断开事件
     */
    @EventListener
    public void handleWebSocketDisconnectListener(SessionDisconnectEvent event) {
        StompHeaderAccessor headerAccessor = StompHeaderAccessor.wrap(event.getMessage());
        String sessionId = headerAccessor.getSessionId();

        log.info("WebSocket连接断开 - Session ID: {}", sessionId);

        try {
            // 1. 先尝试获取玩家所在的房间（用于日志和消息通知）
            Result<GameRoomDto> roomResult = gameServiceClient.getRoomBySessionId(sessionId);
            
            if (roomResult.isFailure() || roomResult.getData() == null) {
                log.info("断线玩家不在任何房间中 - Session ID: {}", sessionId);
                // 即使不在房间中，也要清除玩家基本信息
                clearPlayerInfo(sessionId);
                return;
            }
            
            GameRoomDto room = roomResult.getData();
            String roomId = room.getRoomId();
            int originalPlayerCount = room.getPlayers() != null ? room.getPlayers().size() : 0;
            
            // 2. 先尝试解散房间（只有创建者能成功）
            Result<GameRoomDto> dissolveResult = gameServiceClient.dissolveRoom(sessionId, roomId);
            
            if (dissolveResult.isSuccess()) {
                // 解散成功，说明是创建者
                log.info("房间创建者断线，解散房间: sessionId={}, roomId={}, 原房间人数: {}", 
                        sessionId, roomId, originalPlayerCount);
                // 发送解散房间消息
                messageSendService.notifyRoomDissolved(room);
                log.info("已清理断线创建者房间数据 - Session ID: {}", sessionId);
            } else {
                // 3. 解散失败，尝试离开房间（普通玩家）
                Result<GameRoomDto> leaveResult = gameServiceClient.leaveRoom(sessionId, roomId);
                
                if (leaveResult.isSuccess()) {
                    log.info("玩家断线，离开房间: sessionId={}, roomId={}, 原房间人数: {}", 
                            sessionId, roomId, originalPlayerCount);
                    GameRoomDto updatedRoom = leaveResult.getData();
                    
                    // 先发送离开消息给房间内其他玩家
                    messageSendService.notifyLeave(updatedRoom, sessionId);
                    
                    // 再发送房间更新消息
                    messageSendService.notifyRoomUpdate(updatedRoom);
                    log.info("已清理断线玩家房间数据 - Session ID: {}", sessionId);
                } else {
                    log.warn("玩家离开房间失败: sessionId={}, roomId={}, 错误: {}", 
                            sessionId, roomId, leaveResult.getErrorMessage());
                }
            }
            
            // 4. 无论房间操作是否成功，都要清除玩家基本信息
            clearPlayerInfo(sessionId);
            
        } catch (Exception e) {
            log.error("处理玩家断线事件时发生异常 - Session ID: {}, 异常: {}", sessionId, e.getMessage(), e);
            // 即使发生异常，也要尝试清除玩家信息
            clearPlayerInfo(sessionId);
        }
    }
    
    /**
     * 清除玩家基本信息
     * 
     * @param sessionId 会话ID
     */
    private void clearPlayerInfo(String sessionId) {
        try {
            Result<String> clearResult = gameServiceClient.clearPlayer(sessionId);
            if (clearResult.isSuccess()) {
                log.info("已清除玩家基本信息 - Session ID: {}", sessionId);
            } else {
                log.warn("清除玩家基本信息失败: sessionId={}, 错误: {}", 
                        sessionId, clearResult.getErrorMessage());
            }
        } catch (Exception e) {
            log.error("清除玩家基本信息时发生异常: sessionId={}, 异常: {}", 
                    sessionId, e.getMessage(), e);
        }
    }
}

